package com.demo;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;

public class MainUI extends JFrame {
    private String userId;
    private Map<String, String> shareDataList; // 仅传递String类型的数据，其他类型的数据需另外传
    public String publicKey;
    private String privateKey;
    private MineDialog mineDialog;
    private TxDialog txDialog;
    private WalletDialog walletDialog;
    public Chain myBlockChain;
    public List<Boolean> isSpent = new ArrayList<>();
    private P2PNetwork p2pNetwork;
    private int p2pPort = 5888; // 默认P2P端口

    // 构造函数
    public MainUI(Map<String, String> shareDataList, int port) {
        // 初始化测试链
        initTestChain();

        // 设置P2P端口
        this.p2pPort = port;

        this.shareDataList = shareDataList;
        this.userId = Utils.getValueByKey(this.shareDataList, "userId");
        this.publicKey = Utils.getValueByKey(this.shareDataList, "publicKey");
        this.privateKey =  Utils.getValueByKey(this.shareDataList, "privateKey");

        // 初始化P2P网络
        p2pNetwork = new P2PNetwork(p2pPort, myBlockChain,p2pNetwork.getNodeType(),publicKey);

        setTitle("MyBTC");
        setSize(500, 500);
        // 设置窗口关闭时退出程序
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 设置布局为GridLayout，左右两侧等分
        setLayout(new GridLayout(1, 2, 10, 0)); // 中间等分两侧

        // 左侧面板
        JPanel leftPanel = new JPanel(new GridLayout(3, 1, 10, 10));  // 3行1列布局，按钮之间有间隙
        // "挖矿"按钮
        JButton mineButton = new JButton("挖矿");
        shareDataList.put("difficulty", String.valueOf(myBlockChain.getDifficulty()));
        mineDialog = new MineDialog(shareDataList, myBlockChain, p2pNetwork);
        mineButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // JOptionPane.showMessageDialog(com.demo.MainUI.this, "挖矿功能尚未实现。");
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        mineDialog.setVisible(true);
                    }
                });
            }
        });
        // "交易"按钮
        JButton transactionButton = new JButton("交易");
        txDialog = new TxDialog(shareDataList, this.myBlockChain, this.isSpent, p2pNetwork);
        transactionButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // JOptionPane.showMessageDialog(com.demo.MainUI.this, "交易功能尚未实现。");
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        txDialog.getList();
                        txDialog.setVisible(true);
                    }
                });
            }
        });
        // "钱包"按钮
        JButton walletButton = new JButton("钱包");
        Chain myBlockChainPass = this.myBlockChain;
        List<Boolean> isSpentPass = this.isSpent;
        walletButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // JOptionPane.showMessageDialog(com.demo.MainUI.this, "钱包功能尚未实现。");
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        walletDialog = new WalletDialog(shareDataList,myBlockChainPass,isSpentPass); // 存在显示更新的问题，目前暂时通过每次点击都new一个新的窗口来解决
                        walletDialog.setVisible(true);
                    }
                });
            }
        });
        // 将按钮添加到左侧面板
        leftPanel.add(mineButton);
        leftPanel.add(transactionButton);
        leftPanel.add(walletButton);

        // 右侧面板
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));  // 使用垂直布局

        // 创建用户头像，使用标签显示图像
        ImageIcon originalIcon = new ImageIcon("D:\\BTC_BlockChain_Overwrite\\MyBlockChain_for_BTC\\res\\defaultImg.jpg");
        int rightPanelWidth = getWidth() / 2;
        int rightPanelHeight = getHeight() / 2;
        Image originalImage = originalIcon.getImage();
        Image scaledImage = originalImage.getScaledInstance(rightPanelWidth, rightPanelHeight, Image.SCALE_SMOOTH);
        ImageIcon scaledIcon = new ImageIcon(scaledImage);

        JLabel avatarLabel = new JLabel(scaledIcon);
        avatarLabel.setAlignmentX(Component.CENTER_ALIGNMENT);  // 居中

        // id、公钥和私钥标签
        JLabel userIdLabel = new JLabel("userId: " + userId);
        userIdLabel.setFont(new Font("Arial", Font.PLAIN, 20));
        userIdLabel.setAlignmentX(Component.CENTER_ALIGNMENT);  // 居中

        JLabel publicKeyLabel = new JLabel("pubKey: " + publicKey);
        publicKeyLabel.setFont(new Font("Arial", Font.PLAIN, 20));
        publicKeyLabel.setAlignmentX(Component.CENTER_ALIGNMENT);  // 居中

        JLabel privateKeyLabel = new JLabel("priKey: ****");
        privateKeyLabel.setFont(new Font("Arial", Font.PLAIN, 20));
        privateKeyLabel.setAlignmentX(Component.CENTER_ALIGNMENT);  // 居中

        // 按钮点击显示真实的私钥
        privateKeyLabel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                privateKeyLabel.setText("priKey: "+privateKey);
            }
        });

        // 将头像、公钥、私钥标签添加到右侧面板
        rightPanel.add(avatarLabel);
        rightPanel.add(userIdLabel);
        rightPanel.add(publicKeyLabel);
        rightPanel.add(privateKeyLabel);

        // 将左右面板添加到主窗口
        add(leftPanel);
        add(rightPanel);

        // 创建菜单栏
        JMenuBar menuBar = new JMenuBar();

        // ===========================不重要==========================
        // 文件菜单
        JMenu fileMenu = new JMenu("文件");
        JMenuItem newItem = new JMenuItem("新建");
        JMenuItem exitItem = new JMenuItem("退出");
        exitItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0); // 退出程序
            }
        });
        fileMenu.add(newItem);
        fileMenu.add(exitItem);

        // 编辑菜单
        JMenu editMenu = new JMenu("编辑");
        JMenuItem cutItem = new JMenuItem("剪切");
        JMenuItem copyItem = new JMenuItem("复制");
        editMenu.add(cutItem);
        editMenu.add(copyItem);

        // 帮助菜单
        JMenu helpMenu = new JMenu("帮助");
        JMenuItem aboutItem = new JMenuItem("关于");
        aboutItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(MainUI.this, "比特币钱包 com.demo.MainUI 示例\n版本 1.0");
            }
        });
        helpMenu.add(aboutItem);

        // 将菜单添加到菜单栏
        menuBar.add(fileMenu);
        menuBar.add(editMenu);
        menuBar.add(helpMenu);

        // 设置窗口的菜单栏
        setJMenuBar(menuBar);
        setLocationRelativeTo(null);  // 设置窗体居中显示
        // ===========================不重要==========================

    }

    private void initTestChain() {
        Chain MyBlockChain = new Chain();
        this.myBlockChain = MyBlockChain;
        System.out.println(MyBlockChain.toString());

        // 手动创造交易，并将交易加入到交易池中。交易被创造时就应该被签名
        String testPubKey1 = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBo4DgjA5ZByHWl0NMmXmhPLHv1ZjFomkf27eT5DbapcR1b08ghZLA6Pg8KcFQwtadnJgrtlaynN4EKHkIPFV3g==";
        String testPriKey1 = "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCu9jTfWh/hq8EpG53gGYqwQE/7UdWdpZAi2Ijn6XOOcw==";

        String testPubKey2 = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk+t+uYG05G/HXWDetcGwKSOq2xsx82S7/mDcrN66WKujhsz7S5gR7bH3aExfHuhki8ARNjk3xyZ6zhazQCa/zg==";
        String testPriKey2 = "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCA5Sjuwq2h1Lzk+yy1vcbMrbSAoIiGqCjQK6XGrWxPlIg==";

        String myPubKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUErt/vpIm0xbzEPuQvC5ZCx5PwOepVGzBZK5fRVQ3r4ROKZjFZbwOoLiW1wzhcbxBv7kNge3HWqY6VKlMLqGQw==";
        String myPriKey = "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCNIQ6cHSS/6VlOZbciZx0n+7GHGdAEitRcJmZ38OJj+Q==";

        Transaction tx1 = null; // 出块-1（30）
        Transaction tx2 = null; // 1-我（22）
        try {
            tx1 = new Transaction("出块交易无来源方", testPubKey1, 30);// 伪造成出块交易，供测试
            // 出块交易不需要签名
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            tx2 = new Transaction(testPubKey1, myPubKey, 22);
            tx2.sign(testPriKey1);
            // isSpent.add(false); 应该在验收操作中完成
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(tx1 != null && tx2!= null) {
            try {
                MyBlockChain.addTxToPool(tx1);
                MyBlockChain.addTxToPool(tx2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(MyBlockChain.toString()); // tx1和tx2未被使用到， 因为没有一个区块直接通过传入transactionsPool而实例化

        try {
            MyBlockChain.createBlock(); // 这里的新区块看到了tx1和tx2
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(MyBlockChain.toString());

        try {
            System.out.println(MyBlockChain.validateChain());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 在挖矿成功后广播新区块
    private void broadcastNewBlock(Block block) {
        p2pNetwork.broadcastBlock(block);
    }

    // 在创建交易后广播交易
    private void broadcastNewTransaction(Transaction tx) {
        p2pNetwork.broadcastTransaction(tx);
    }

    // 添加连接其他节点的方法
    public void connectToNode(String ip, int port) {
        p2pNetwork.connectToPeer(ip, port);
    }

    // 在窗口关闭时清理资源
    @Override
    public void dispose() {
        p2pNetwork.shutdown();
        super.dispose();
    }

    // 主方法
    public static void main(String[] args) {
        // 创建和显示界面
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                Map<String, String> testList = new HashMap<>();
                testList.put("userId", "nihao");
                testList.put("publicKey", "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEUErt/vpIm0xbzEPuQvC5ZCx5PwOepVGzBZK5fRVQ3r4ROKZjFZbwOoLiW1wzhcbxBv7kNge3HWqY6VKlMLqGQw==");
                testList.put("privateKey", "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCNIQ6cHSS/6VlOZbciZx0n+7GHGdAEitRcJmZ38OJj+Q==");

                // 从命令行参数获取端口号
                int port = 5888;
                if (args.length > 0) {
                    try {
                        port = Integer.parseInt(args[0]);
                        System.out.println("使用端口号: " + port);
                    } catch (NumberFormatException e) {
                        System.out.println("无效的端口号，使用默认端口5888");
                    }
                }

                MainUI mainUi = new MainUI(testList, port);
                mainUi.setVisible(true);

                // 添加连接测试节点的按钮
                JButton connectButton = new JButton("连接测试节点");
                connectButton.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        String ip = JOptionPane.showInputDialog("请输入要连接的节点IP地址：");
                        String portStr = JOptionPane.showInputDialog("请输入要连接的节点端口：");
                        if (ip != null && portStr != null) {
                            try {
                                int peerPort = Integer.parseInt(portStr);
                                mainUi.connectToNode(ip, peerPort);
                                JOptionPane.showMessageDialog(null, "连接请求已发送！");
                            } catch (NumberFormatException ex) {
                                JOptionPane.showMessageDialog(null, "无效的端口号！");
                            }
                        }
                    }
                });
                mainUi.add(connectButton);
            }
        });
    }
}
